package com.dldata.devtools30.controller.sysform;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dldata.devtools30.common.EnumUtils;
import com.dldata.devtools30.entity.*;
import com.dldata.devtools30.repository.sysform.DevtFormDesignEntityDao;
import com.dldata.devtools30.repository.sysform.DevtFormFieldCheckDao;
import com.dldata.devtools30.repository.sysform.DevtFormFieldConfigDao;
import com.dldata.devtools30.repository.sysform.DevtFormMetadataDao;
import com.dldata.devtools30.service.metadata.DevtModelMetadataFieldService;
import com.dldata.devtools30.service.metadata.DevtModelMetadataTableService;
import com.dldata.devtools30.service.sysform.DevtFormDesignEntityService;
import com.dldata.devtools30.utils.Public;
import com.dldata.devtools30.utils.Result;
import com.dldata.devtools30.utils.RightUtil;
import com.dldata.devtools30.utils.StringUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.Timestamp;
import java.util.*;

/**
 * Created by zhw on 2020-08-17.
 */
@Controller
@RequestMapping(value = "/DevtFormDesignEntityController")
@Slf4j
public class DevtFormDesignEntityController {
    
    @Autowired
    ApplicationContext applicationContext;
    @Autowired
    DevtFormDesignEntityDao formDesignDao;
    @Autowired
    DevtFormFieldConfigDao formDesignFieldConfigDao;
    @Autowired
    DevtFormDesignEntityService formDesignService;
    @Autowired
    DevtFormMetadataDao sysCrfFormMetadataDao;
    @Autowired
    DevtModelMetadataTableService metadataTableService;
    @Autowired
    DevtModelMetadataFieldService metadataFieldService;
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    NamedParameterJdbcTemplate npJdbcTemplate;
    @Autowired
    DevtFormFieldCheckDao sysFormFieldCheckDao;

    @RequestMapping("/toSave")
    @ResponseBody
    public Result toSysFormTypeList(@RequestParam Map param){

        try {

            String tempid = param.get("pid").toString();

            JSONObject jsonopt = JSONObject.parseObject(param.get("jsonopt").toString());
            String jsonoptStr = jsonopt.get("list").toString();
            String configStr = jsonopt.get("config").toString();

            JSONObject configObj = JSONObject.parseObject(configStr);
            String name = configObj.get("name").toString();
            String width = configObj.get("width").toString();
            String height = configObj.get("height").toString();

            List<DevtFormDesignEntity> formDesignEntityList = formDesignService.getFormDesignDataByTempid(tempid);
            if (formDesignEntityList.size()>0){
                formDesignService.deleteDataByTempid(tempid);
            }
            List<DevtFormFieldConfigEntity> formDesignFieldConfigEntityList = formDesignFieldConfigDao.getFormDesignDataByTempid(tempid);
            if (formDesignFieldConfigEntityList.size()>0){
                formDesignFieldConfigDao.deleteAll(formDesignFieldConfigEntityList);
            }

            DevtFormDesignEntity designEntity = new DevtFormDesignEntity();
            designEntity.setId(UUID.randomUUID().toString());
            designEntity.setTemplateid(tempid);
            designEntity.setHeight(height);
            designEntity.setJsonOpt(param.get("jsonopt").toString());
            designEntity.setName(name);
            designEntity.setWidth(width);
            formDesignDao.save(designEntity);

            JSONArray postlist = JSONArray.parseArray(param.get("postlist").toString());

            for (Object postData : postlist) {
                Map map = (Map) postData;
                DevtFormFieldConfigEntity configEntity = new DevtFormFieldConfigEntity();
                configEntity.setId(UUID.randomUUID().toString());
                configEntity.setTemplateid(tempid);
                configEntity.setDatasql(map.get("datasql").toString());
                configEntity.setTablecode(map.get("fieldid").toString().split("@")[0]);
                configEntity.setFieldid(map.get("fieldid").toString().split("@")[1]);
                formDesignFieldConfigDao.save(configEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("保存异常");
        }

        return Result.ok();
    }


    @RequestMapping("/getFormDesignDataByTempid")
    @ResponseBody
    public Result getFormDesignDataByTempid(String tempid){
        List<DevtFormDesignEntity> formDesignEntityList = formDesignService.getFormDesignDataByTempid(tempid);

        if (formDesignEntityList.size()==0){
            return Result.error("未找到表单配置表数据");
        }
        List<DevtFormFieldConfigEntity> formDesignFieldConfigEntityList = formDesignFieldConfigDao.getFormDesignDataByTempid(tempid);

        if (formDesignFieldConfigEntityList.size()==0){
            return Result.error("未找到配置字段表数据");
        }

        Map resultMap = new HashMap();
        resultMap.put("FormDesignEntity",formDesignEntityList.get(0));
        resultMap.put("FieldConfigList",formDesignFieldConfigEntityList);

        return Result.ok(resultMap);
    }
    
    @RequestMapping("/toPreviewSave")
    @ResponseBody
    public Result toPreviewSave(@RequestParam Map param){
        DevtFormMetadataEntity sysFormMetadataEntity = sysCrfFormMetadataDao.getDataByTempleid(param.get("tempid").toString()).get(0);
        DevtModelMetadataTableEntity metadataTableEntity = metadataTableService.findOne(sysFormMetadataEntity.getTableid());
        if(EnumUtils.StoreTypeEnum.普通.name().equals(metadataTableEntity.getStoretype())){
            return toPreviewSaveTable(param);
        }
        return toPreviewSaveJson(param);
    }
    
    @RequestMapping("/toPreviewSaveJson")
    @ResponseBody
    public Result toPreviewSaveJson(@RequestParam Map param){
        JSONArray jsonArray = JSONArray.parseArray(param.get("strlist").toString());
        HashMap valueMap=new HashMap();
        String tablenameop="";
        for (Object str : jsonArray) {
            JSONObject strObject = JSONObject.parseObject(str.toString());
            String tablename=tablenameop=strObject.get("id").toString().split("@")[0];
            String fieldcode=strObject.get("id").toString().split("@")[1];
            Object value = strObject.get("value");
            //ID为空则创建一个ID
            if(fieldcode.equalsIgnoreCase("ID")&&StringUtil.isEmptyOrLength0(value)){
                value=UUID.randomUUID().toString();
            }
            valueMap.put(fieldcode,value);
        }
        
        String insertsql=" insert into  "+tablenameop+"(id,_usercode,_createtime,_updatetime,jsondata,_datatime) values (:id,:_usercode,:_createtime,:_updatetime,:jsondata,:_datatime )";
        String updatesql=" update "+ tablenameop + " set _usercode=:_usercode,_updatetime=:_updatetime,jsondata=:jsondata,_datatime=:_datatime where id=:id";
        String selectsql=" select id from "+ tablenameop + " where id=:id";
        
        CaseInsensitiveMap insensitiveMap = new CaseInsensitiveMap(valueMap);
        if(StringUtil.isEmptyOrLength0(insensitiveMap.get("id"))){
            valueMap.put("ID",UUID.randomUUID().toString());
            insensitiveMap.put("id",valueMap.get("ID"));
        }
        HashMap paraMap=new HashMap();
        paraMap.put("id",insensitiveMap.get("id"));
        List queryForList = npJdbcTemplate.queryForList(selectsql, paraMap);
        if(queryForList.size()==0){
            paraMap.put("_usercode", RightUtil.getCurrentUser(Public.getRequest()).getDevtooluser());
            paraMap.put("_createtime",new Timestamp(System.currentTimeMillis()));
            paraMap.put("_updatetime",new Timestamp(System.currentTimeMillis()));
            paraMap.put("_datatime",insensitiveMap.get("datatime"));
            paraMap.put("jsondata", JSON.toJSONStringWithDateFormat(valueMap,"yyyy-MM-dd HH:mm:ss.SSS"));
            npJdbcTemplate.update(insertsql,paraMap);
        }else{
            paraMap.put("_usercode", RightUtil.getCurrentUser(Public.getRequest()).getDevtooluser());
            paraMap.put("_updatetime",new Timestamp(System.currentTimeMillis()));
            paraMap.put("_datatime",insensitiveMap.get("datatime"));
            paraMap.put("jsondata", JSON.toJSONStringWithDateFormat(valueMap,"yyyy-MM-dd HH:mm:ss.SSS"));
            npJdbcTemplate.update(updatesql,paraMap);
        }
        
        return Result.ok();
    }

    @RequestMapping("/toPreviewSaveTable")
    @ResponseBody
    public Result toPreviewSaveTable(@RequestParam Map param){

        try {
            JSONArray jsonArray = JSONArray.parseArray(param.get("strlist").toString());

            //SQL校验
            List<DevtFormFieldcheckEntity> customTypeEntityList = sysFormFieldCheckDao.getActieFormFieldCheckByFormId(param.get("tempid").toString());
            for (DevtFormFieldcheckEntity sqlCheck : customTypeEntityList) {
                if (sqlCheck.getActive() == 0) {
                    continue;
                }
                if (!sqlCheck.getChecktype().equalsIgnoreCase("customsql")) {
                    continue;
                }
                String sqlCheckStr = sqlCheck.getContent();
                for (Object str : jsonArray) {
                    JSONObject strObject = JSONObject.parseObject(str.toString());
                    if (sqlCheckStr.indexOf(strObject.get("id").toString()) > 0) {
                        sqlCheckStr = sqlCheckStr.replace("[" + strObject.get("id").toString() + "]", strObject.get("value").toString());
                        System.out.println(sqlCheckStr);
                    }
                }
                List list = jdbcTemplate.queryForList(sqlCheckStr);
                if (list.size() > 0) {
                    return Result.error(sqlCheck.getErrorinfo());
                }
            }
            /****************************第三方数据保存**********************************/

            List<DevtFormMetadataEntity> crfFormMetadataEntityList = Lists.newArrayList(sysCrfFormMetadataDao.findAll());
            List<DevtModelMetadataTableEntity> tableEntities = metadataTableService.getAll();
            List<Map<String, Object>> mapList = new ArrayList<>();
            crfFormMetadataEntityList.stream().filter(w ->
                    w.getTempleid().equals(param.getOrDefault("tempid", "")))
                    .forEach(m -> {
                        Map<String, Object> data = new HashMap<>();
                        data.put("id", m.getId());
                        data.put("name", "");
                        data.put("code", "");
                        data.put("tableid", "");
                        data.put("tabletype", "");
                        tableEntities.stream().filter(w -> w.getId().equals(m.getTableid())).forEach(tm -> {
                            data.put("tableid", m.getTableid());
                            data.put("tabletype", m.getTabletype());
                            if ("父表".equalsIgnoreCase(m.getTabletype())){
                                data.put("xh", "0");
                            }else {
                                data.put("xh", "1");
                            }
                            data.put("name", tm.getName());
                            data.put("code", tm.getCode());
                        });
                        mapList.add(data);
                    });


            Collections.sort(mapList, new Comparator<Map<String, Object>>() {
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    Integer name1 = Integer.valueOf(o1.get("xh").hashCode()) ; //list里面拿出来的一个
                    Integer name2 = Integer.valueOf(o2.get("xh").hashCode()) ; //list里面拿出来的第二个
                    return name1.compareTo(name2);
                }
            });

            Map sqlMap = new LinkedHashMap();

            Map pidMap = new HashMap();

            System.out.println("");
            mapList.stream().forEach(tableMap -> {
                List<DevtModelMetadataFieldEntity> fieldEntityList = metadataFieldService.getAllByTid(tableMap.get("tableid").toString());
                Map map = new LinkedCaseInsensitiveMap();
                sqlMap.put(tableMap.get("code"), map);
                fieldEntityList.stream().forEach(field -> {
//                    map.put(field.getFieldCode(), "");
                    for (Object str : jsonArray) {
                        JSONObject strObject = JSONObject.parseObject(str.toString());
                        if (tableMap.get("code").toString().equalsIgnoreCase(strObject.get("id").toString().split("@")[0])
                                && field.getFieldCode().equalsIgnoreCase(strObject.get("id").toString().split("@")[1])) {
                            map.put(field.getFieldCode(), strObject.get("value"));
                        }
                    }

                    if ((mapList.size()==1|| "父表".equals(tableMap.getOrDefault("tabletype","")) )
                            && !StringUtil.isEmptyOrLength0(param.get("dataid"))
                            && StringUtil.isEmptyOrLength0(map.get(field.getFieldCode()))
                            && field.getPkey() == 1) {
                        String tempSql = "select * from " + tableMap.get("code").toString() + " where id " + "='" + param.get("dataid").toString() + "'";
                        List<Map<String, Object>> list = jdbcTemplate.queryForList(tempSql);
                        if (list.size() > 0) {
                            map.put(field.getFieldCode(), list.get(0).get("id"));
                        }
                    }

                    if ("子表".equals(tableMap.getOrDefault("tabletype","")) && !StringUtil.isEmptyOrLength0(param.get("dataid")) && StringUtil.isEmptyOrLength0(map.get(field.getFieldCode())) && field.getPkey() == 1) {
                        List<DevtModelMetadataFieldEntity> fieldList = metadataFieldService.getAllByTid(tableMap.get("tableid").toString());
                        for (DevtModelMetadataFieldEntity fieldEntity : fieldList) {
                            if (("是").equalsIgnoreCase(fieldEntity.getTabletype())) {
                                String tempSql = "select * from " + tableMap.get("code").toString() + " where " + fieldEntity.getFieldCode() + "='" + param.get("dataid").toString() + "'";
                                List<Map<String, Object>> list = jdbcTemplate.queryForList(tempSql);
                                if (list.size() > 0) {
                                    map.put(field.getFieldCode(), list.get(0).get("id"));
                                    break;
                                }
                            }
                        }
                    }

                    if (field.getPkey() == 1 && StringUtil.isEmptyOrLength0(map.get(field.getFieldCode()))) {
                        map.put(field.getFieldCode(), UUID.randomUUID().toString());
                    }
                    

                    if (("是").equalsIgnoreCase(field.getTabletype())) {
                        Map map1 = (Map) sqlMap.get(metadataTableService.findOne(field.getPatienttable()).getCode());
                        if (!StringUtil.isEmptyOrLength0(map1)&&map1.size()>0) {
                            String pid = map1.get(field.getPatienttablefield()).toString();
                            map.put(field.getFieldCode(), pid);

                            pidMap.put(tableMap.get("code") + "#" + field.getFieldCode(), "");
                        }
                    }

                });
                sqlMap.put(tableMap.get("code"), map);
            });

            Set keySet = sqlMap.keySet();

            for (Object keyName : keySet) {

                List list = new ArrayList();
                Map tempMap = (Map) sqlMap.get(keyName);

                if (!StringUtil.isEmptyOrLength0(param.get("dataid"))) {

                    String tableName = keyName.toString();
                    String fieldName = "id";

                    Set pidMapSetKey = pidMap.keySet();
                    for (Object pidMapKeyName : pidMapSetKey) {
                        String tableKey[] = pidMapKeyName.toString().split("#");
                        if (keyName.toString().equalsIgnoreCase(tableKey[0])) {
                            keyName = tableKey[0];
                            fieldName = tableKey[1];
                        }
                    }

                    String tempSql = "select * from " + tableName + " where " + fieldName + "='" + param.get("dataid").toString() + "'";
                    list = jdbcTemplate.queryForList(tempSql);
                }

                if (list.size() > 0) {
                    StringBuilder sql = new StringBuilder("update " + keyName);
                    Map paramMap = new LinkedHashMap();
                    Set key = tempMap.keySet();
                    sql.append(" set ");
                    for (Object fieldName : key) {
                        sql.append(fieldName + "=:" + fieldName + "");
                        sql.append(",");
                        paramMap.put(fieldName, tempMap.get(fieldName));
                    }

                    if (sql.toString().endsWith(",")) {
                        sql = new StringBuilder(sql.substring(0, sql.length() - 1));
                    }

                    sql.append(" where id = :id ");
                    paramMap.put("id", tempMap.get("ID"));
                    log.debug(sql.toString());
                    log.debug(JSON.toJSONString(paramMap));
                    npJdbcTemplate.update(sql.toString(), paramMap);

                } else {
                    StringBuilder sql = new StringBuilder("insert into " + keyName);
                    StringBuilder sqlKey = new StringBuilder("(");
                    StringBuilder sqlValue = new StringBuilder("(");
                    Map paramMap = new LinkedHashMap();


                    Set key = tempMap.keySet();
                    int num = 0;
                    for (Object name : key) {
                        if (!StringUtil.isEmptyOrLength0(tempMap.get(name))) {
                            sqlKey.append(name);
                            sqlValue.append(":" + name);
                            paramMap.put(name, tempMap.get(name).toString());
                        }
                        if (num < key.size() - 1 && !StringUtil.isEmptyOrLength0(tempMap.get(name))) {
                            sqlKey.append(",");
                            sqlValue.append(",");
                        }
                        num++;
                    }
                    if (sqlKey.toString().endsWith(",")) {
                        sqlKey = new StringBuilder(sqlKey.substring(0, sqlKey.length() - 1));
                    }

                    if (sqlValue.toString().endsWith(",")) {
                        sqlValue = new StringBuilder(sqlValue.substring(0, sqlValue.length() - 1));
                    }

                    sqlKey.append(")");
                    sqlValue.append(")");

                    sql.append(sqlKey);
                    sql.append(" values ");
                    sql.append(sqlValue);

                    System.out.println(sql);
                    npJdbcTemplate.update(sql.toString(), paramMap);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage());
        }
        return Result.ok();

    }

}
